/*!
 * HeadJS    
 * Version 0.99
 * 云淡然再次修改 v1.0
 * 并行加载，顺序执行
 * 使用方法1：head.load(["js1","../js2"],function(){});
 * 使用方法2：head.load("js1",function(){});
 */
;
(function(win, undefined) {
	"use strict";

	var
		doc = win.document,
		domWaiters = [],
		queue = [],
		handlers = {},
		assets = {},
		isHeadReady,
		isDomReady,

		headVar = win.head_conf && win.head_conf.head || "head",
		api = win[headVar] = (win[headVar] || function() {
			api.ready.apply(null, arguments);
		}),

		PRELOADING = 1,
		PRELOADED = 2,
		LOADING = 3,
		LOADED = 4,

		js, jsArr = [];

	api.script = thisScript();

	js = api.script.getAttribute("data-js"),
		jsArr = js ? js.split(",") : [];

	api.load = function() {
		var
			args = arguments,
			jsArr = args[0],
			callback = args[1],
			items = {};

		if (!isFunction(callback)) {
			callback = null;
		}

		if (!isArray(jsArr))
			jsArr = new Array(jsArr);

		each(jsArr, function(item, i) {
			item = getFilePath(item);
			item = getAsset(item);
			items[item.name] = item;

			load(item, callback && i === jsArr.length - 1 ?
				function() {
					if (allLoaded(items)) {
						one(callback);
					}
				} :
				null);

		});

		return api;
	};

	api.baseUrl = baseUrl();

	function noop() {

	}

	function each(arr, callback) {
		if (!arr) {
			return;
		}

		if (typeof arr === 'object') {
			arr = [].slice.call(arr);
		}

		for (var i = 0, l = arr.length; i < l; i++) {
			callback.call(arr, arr[i], i);
		}
	}

	function is(type, obj) {
		var clas = Object.prototype.toString.call(obj).slice(8, -1);
		return obj !== undefined && obj !== null && clas === type;
	}

	function isFunction(item) {
		return is("Function", item);
	}

	function isArray(item) {
		return is("Array", item);
	}

	function toLabel(url) {
		var items = url.split("/"),
			name = items[items.length - 1],
			i = name.indexOf("?");

		return i !== -1 ? name.substring(0, i) : name;
	}

	function one(callback) {
		callback = callback || noop;

		if (callback._done) {
			return;
		}

		callback();
		callback._done = 1;
	}

	function getAsset(item) {
		var asset = {};

		if (typeof item === 'object') {
			for (var label in item) {
				if (!!item[label]) {
					asset = {
						name: label,
						url: item[label]
					};
				}
			}
		} else {
			asset = {
				name: toLabel(item),
				url: item
			};
		}

		var existing = assets[asset.name];
		if (existing && existing.url === asset.url) {
			return existing;
		}

		assets[asset.name] = asset;
		return asset;
	}

	function allLoaded(items) {
		items = items || assets;

		for (var name in items) {
			if (items.hasOwnProperty(name) && items[name].state !== LOADED) {
				return false;
			}
		}

		return true;
	}

	function onPreload(asset) {
		asset.state = PRELOADED;

		each(asset.onpreload, function(afterPreload) {
			afterPreload.call();
		});
	}

	function preLoad(asset, callback) {
		if (asset.state === undefined) {

			asset.state = PRELOADING;
			asset.onpreload = [];

			loadAsset({
				url: asset.url,
				type: 'cache'
			}, function() {
				onPreload(asset);
			});
		}
	}

	function load(asset, callback) {
		callback = callback || noop;

		if (asset.state === LOADED) {
			callback();
			return;
		}

		if (asset.state === LOADING) {
			// api.ready(asset.name, callback);
			return;
		}

		if (asset.state === PRELOADING) {
			asset.onpreload.push(function() {
				load(asset, callback);
			});
			return;
		}

		asset.state = LOADING;

		loadAsset(asset, function() {
			asset.state = LOADED;
			callback();

			each(handlers[asset.name], function(fn) {
				one(fn);
			});

			if (isDomReady && allLoaded()) {
				each(handlers.ALL, function(fn) {
					one(fn);
				});
			}
		});
	}

	function loadAsset(asset, callback) {
		callback = callback || noop;

		var ele;
		if (/\.css[^\.]*$/.test(asset.url)) {
			ele = doc.createElement('link');
			ele.type = 'text/' + (asset.type || 'css');
			ele.rel = 'stylesheet';
			ele.href = asset.url;
		} else {
			ele = doc.createElement('script');
			ele.type = 'text/' + (asset.type || 'javascript');
			ele.src = asset.url;
		}

		ele.onload = ele.onreadystatechange = process;
		ele.onerror = error;
		ele.async = false;
		ele.defer = false;

		function error(event) {
			event = event || win.event;
			ele.onload = ele.onreadystatechange = ele.onerror = null;
			callback();
		}

		function process(event) {
			event = event || win.event;
			if (event.type === 'load' || (/loaded¦complete/.test(ele.readyState) && (!doc.documentMode || doc.documentMode < 9))) {
				ele.onload = ele.onreadystatechange = ele.onerror = null;
				callback();
			}
		}
		var head = doc['head'] || doc.getElementsByTagName('head')[0];
		head.insertBefore(ele, head.lastChild);
	}

	function domReady() {
		if (!doc.body) {
			win.clearTimeout(api.readyTimeout);
			api.readyTimeout = win.setTimeout(domReady, 50);
			return;
		}

		if (!isDomReady) {
			isDomReady = true;
			each(domWaiters, function(fn) {
				one(fn);
			});
		}
	}

	function domContentLoaded() {
		// W3C
		if (doc.addEventListener) {
			doc.removeEventListener("DOMContentLoaded", domContentLoaded, false);
			domReady();
		}

		// IE
		else if (doc.readyState === "complete") {
			doc.detachEvent("onreadystatechange", domContentLoaded);
			domReady();
		}
	};

	if (doc.readyState === "complete") {
		domReady();
	}

	// W3C
	else if (doc.addEventListener) {
		doc.addEventListener("DOMContentLoaded", domContentLoaded, false);
		win.addEventListener("load", domReady, false);
	}

	// IE
	else {
		doc.attachEvent("onreadystatechange", domContentLoaded);
		win.attachEvent("onload", domReady);
		var top = false;

		try {
			top = win.frameElement == null && doc.documentElement;
		} catch (e) {}

		if (top && top.doScroll) {
			(function doScrollCheck() {
				if (!isDomReady) {
					try {
						top.doScroll("left");
					} catch (error) {
						win.clearTimeout(api.readyTimeout);
						api.readyTimeout = win.setTimeout(doScrollCheck, 50);
						return;
					}
					domReady();
				}
			})();
		}
	}

	setTimeout(function() {
		isHeadReady = true;
		each(queue, function(fn) {
			fn();
		});

	}, 300);

	function thisScript() {
		var
			scripts = document.getElementsByTagName('script'),
			script = scripts[scripts.length - 1];
		return script;
	}

	// 基准路径
	function baseUrl() {
		var result;
		if (!result) {
			result = api.script.src;
		}
		return result.indexOf('/') >= 0 ?
			result.substr(0, result.lastIndexOf('/')) + '/' :
			'';
	}

	// 智能获取路径
	function getFilePath(file) {
		// 相对路径还是绝对路径
		if (!/^http(s)?:\/\//.test(file)) {
			// 智能判断是否有.js后缀
			// file=api.baseUrl+file+(/\.js$¦\.js?.*$/.test(file)?'':'.js');
		}
		return file;
	}

	// 自运行
	if (jsArr.length > 0) api.load(jsArr);

})(window);